package com.bh.weapp.controller.sysuser.code;

import com.bh.common.annotation.Log;
import com.bh.common.enums.OrderStatus;
import com.bh.common.enums.ShipmentStatus;
import com.bh.common.constant.Symbol;
import com.bh.common.core.controller.BaseController;
import com.bh.common.core.domain.AjaxResult;
import com.bh.common.core.page.TableDataInfo;
import com.bh.common.enums.BusinessType;
import com.bh.common.utils.RedisCodeUtil;
import com.bh.common.utils.SecurityUtils;
import com.bh.common.utils.StringUtils;
import com.bh.common.utils.uuid.IdUtils;
import com.bh.extend.domain.JcLedSend;
import com.bh.extend.domain.JcOrderBarcode;
import com.bh.extend.service.IJcLedSendService;
import com.bh.extend.service.IJcOrderBarcodeService;
import com.bh.extend.vo.*;
import com.bh.order.domain.JcLed;
import com.bh.order.domain.JcOrder;
import com.bh.order.service.IJcLedService;
import com.bh.order.service.IJcOrderService;
import com.bh.shipment.domain.JcShipment;
import com.bh.shipment.domain.JcVehicleArrive;
import com.bh.shipment.service.IJcShipmentService;
import com.bh.shipment.service.IJcVehicleArriveService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 条码与商品对应Controller
 *
 * @author slx
 * @date 2023-05-24
 */
@Transactional(rollbackFor = Exception.class)
@Api(tags = {"SYS产品扫码"})
@RestController
@RequestMapping("/api/sysuser/barcode")
public class JcOrderBarcodeSysApiController extends BaseController {

    @Autowired
    private IJcOrderBarcodeService jcOrderBarcodeService;
    @Autowired
    private IJcShipmentService jcShipmentService;
    @Autowired
    private IJcVehicleArriveService vehicleArriveService;
    @Autowired
    private IJcOrderService jcOrderService;
    @Autowired
    private IJcLedService jcLedService;
    @Autowired
    private IJcLedSendService jcLedSendService;
    @Autowired
    private RedisCodeUtil redisCodeUtil;

    /**
     * 修改保存条码与商品对应，只是用于修改商品装车状态，只有保存的时候才需要真正装载
     */
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("商品扫码装车")
    @Log(title = "条码与商品对应", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('api:barcode:load:scan')")
    @PostMapping("/scanCode")
    public AjaxResult scanCode(@RequestBody @Validated JcOrderBarcodeScanVo orderBarcodeVo) {
        if (StringUtils.isBlank(orderBarcodeVo.getProductCode())) {
            return error("条码不能为空");
        }
        JcShipment shipment = jcShipmentService.selectJcShipmentById(orderBarcodeVo.getShipmentId());
        orderBarcodeVo.setProductCode(orderBarcodeVo.getProductCode().trim().replace("－", "-"));

        if (shipment.getStatus() != OrderStatus.ACTIVE.getValue()) {
            return error("该运单已经扫码装车完成！");
        }
        List<JcOrderBarcode> barcodes = new ArrayList<>();
        if (StringUtils.isNotBlank(orderBarcodeVo.getEndProductCode()) && !Objects.equals(orderBarcodeVo.getProductCode(), orderBarcodeVo.getEndProductCode())) {
            orderBarcodeVo.setEndProductCode(orderBarcodeVo.getEndProductCode().trim().replace("－", "-"));
            JcOrderBarcode first = jcOrderBarcodeService.selectJcOrderBarcodeByProductCode(orderBarcodeVo.getProductCode());
            JcOrderBarcode end = jcOrderBarcodeService.selectJcOrderBarcodeByProductCode(orderBarcodeVo.getEndProductCode());
            if (!Objects.equals(first.getLedOrderId(), end.getLedOrderId())) {
                return error("请扫码同一分段订单的商品！");
            }
            barcodes = jcOrderBarcodeService.selectJcOrderBarcode(first.getLedOrderId(), first.getOrderBy(), end.getOrderBy());
            if (barcodes == null || barcodes.size() == 0) {
                return error("条码与商品对应不匹配");
            }
            for (JcOrderBarcode barcode : barcodes) {
                barcode.setShipmentId(orderBarcodeVo.getShipmentId());
                barcode.setPackStatus("Y");
                barcode.setPackTime(new Date());
            }
        } else {
            // 如果条码为空,则更新
            JcOrderBarcode barcode = jcOrderBarcodeService.selectJcOrderBarcodeByProductCode(orderBarcodeVo.getProductCode());
            if (barcode == null) {
                return error("条码与商品对应不匹配");
            }
            if ("Y".equals(barcode.getPackStatus())) {
                return error("商品已经装车,请勿重复装箱");
            }
            barcode.setShipmentId(orderBarcodeVo.getShipmentId());
            barcode.setPackStatus("Y");
            barcode.setPackTime(new Date());
            barcodes.add(barcode);
        }
        // 判断订单
        JcOrder order = jcOrderService.getById(barcodes.get(0).getOrderId());
        if (order.getStatus() < OrderStatus.CONFIGRM.getValue()) {
            return error("该商品对应的订单还未确认，请确认订单！");
        }
        JcLed led = jcLedService.getById(barcodes.get(0).getLedOrderId());
        if (led.getStatus() != OrderStatus.CONFIGRM.getValue()) {
            return error("该商品对应的分段订单已经完成，请确认订单！");
        }
        // 判断是否和运单路线一致，为了避免出现转运无法进行装货的情况，所以需要通过路线来判断，路由中除了出发点以外的任意一点在运单的路线范围内都可以进行装货
        String[] routerOrgIds = order.getRouterOrgIds().split(Symbol.COMMA);
        boolean isSame = false;
        for (int i = 0; i < routerOrgIds.length; i++) {
            if (i == 0) {
                // 目前出发地址必须要保持一致，后续可能会增加中途装货的流程（--TODO）
                if (!shipment.getJcFromOrganizationId().equals(Long.valueOf(routerOrgIds[i]))) {
                    break;
                }
            } else {
                if ((shipment.getOrgIds() != null && shipment.getOrgIds().contains(routerOrgIds[i])) || shipment.getJcToOrganizationId().equals(Long.valueOf(routerOrgIds[i]))) {
                    isSame = true;
                    break;
                }
            }
        }
        if (!isSame) {
            return error("该商品对应的订单路线和运单不一致，请核对后再扫码！");
        }
        return toAjax(jcOrderBarcodeService.updateBatchById(barcodes));
    }


    /**
     * 移除装载状态
     */
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("移除商品装车")
    @Log(title = "条码与商品对应", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('api:barcode:load:remove')")
    @PostMapping("/removeCode/{productCode}")
    public AjaxResult removeCode(@PathVariable("productCode") String productCode) {
        if (StringUtils.isBlank(productCode)) {
            return error("条码不能为空");
        }
        return toAjax(jcOrderBarcodeService.removeJcOrderBarcodePack(productCode));
    }


    /**
     * 查询连续条码与商品对应列表
     *
     * @return 条码与商品对应集合
     */
    @ApiOperation("查询装车商品")
    @PreAuthorize("@ss.hasPermi('api:barcode:load:list')")
    @GetMapping("/getLoadProductList")
    public TableDataInfo selectLoadProductList(JcOrderBarcodeQueryVo pageVo) {
        JcOrderBarcode jcOrderBarcode = new JcOrderBarcode();
        jcOrderBarcode.setShipmentId(pageVo.getShipmentId());
        jcOrderBarcode.setLedOrderId(pageVo.getLedId());
        startPage();
        List<JcOrderBarcode> list = jcOrderBarcodeService.selectJcOrderBarcodeList(jcOrderBarcode);
        return getDataTable(list);
    }


    /**
     * 修改保存条码与商品对应，只是用于修改商品装车状态，只有保存的时候才需要真正装载
     */
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("商品扫码卸车")
    @Log(title = "条码与商品对应", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('api:barcode:unload')")
    @PostMapping("/scanCodeUnload")
    public AjaxResult scanCodeUnload(@RequestBody @Validated JcOrderBarcodeUnloadScanVo orderBarcodeVo) {
        if (StringUtils.isBlank(orderBarcodeVo.getProductCode())) {
            return error("条码不能为空");
        }
        JcShipment shipment = jcShipmentService.selectJcShipmentById(orderBarcodeVo.getShipmentId());
        if (shipment.getStatus() < ShipmentStatus.DESPATCH.getValue()) {
            return error("该运单禁止卸货！");
        }
        orderBarcodeVo.setProductCode(orderBarcodeVo.getProductCode().trim().replace("－", "-"));

        JcOrderBarcode first = jcOrderBarcodeService.selectJcOrderBarcodeByProductCode(orderBarcodeVo.getProductCode());
        if (first == null) {
            return error("条码与商品对应不匹配");
        }

        JcLed led = jcLedService.getById(first.getLedOrderId());
        if (led.getStatus() != OrderStatus.DESPATCH.getValue() && led.getStatus() != OrderStatus.ARRIVE.getValue()) {
            return error("该商品对应的分段订单已经完成卸货，请确认订单！");
        }
        // 当前站点和订单结束站点必须保持一致
        if (!Objects.equals(led.getJcToOrganizationId(), shipment.getJcNowOrganizationId())) {
            return error("该商品不属于当前站点，请核对后再扫码卸货！");
        }
        // 判断订单
        JcOrder order = jcOrderService.getById(first.getOrderId());
        // 判断是否和运单路线一致
        String[] routerOrgIds = order.getRouterOrgIds().split(Symbol.COMMA);
        boolean isSame = false;
        for (int i = 0; i < routerOrgIds.length; i++) {
            if (i == 0) {
                // 目前出发地址必须要保持一致，后续可能会增加中途装货的流程（--TODO）
                if (!shipment.getJcFromOrganizationId().equals(Long.valueOf(routerOrgIds[i]))) {
                    break;
                }
            } else {
                if (shipment.getOrgIds() != null && shipment.getOrgIds().contains(routerOrgIds[i]) || shipment.getJcToOrganizationId().equals(Long.valueOf(routerOrgIds[i]))) {
                    isSame = true;
                    break;
                }
            }
        }
        if (!isSame) {
            first.setAbnormalScanTime(new Date());
            first.setAbnormalScanUser(getUsername());
            jcOrderBarcodeService.updateById(first);
            return error("该商品对应的订单路线和运单不一致，请核对后再扫码！");
        }

        List<JcOrderBarcode> barcodes = new ArrayList<>();
        if (StringUtils.isNotBlank(orderBarcodeVo.getEndProductCode()) && !Objects.equals(orderBarcodeVo.getProductCode(), orderBarcodeVo.getEndProductCode())) {
            orderBarcodeVo.setEndProductCode(orderBarcodeVo.getEndProductCode().trim().replace("－", "-"));
            JcOrderBarcode end = jcOrderBarcodeService.selectJcOrderBarcodeByProductCode(orderBarcodeVo.getEndProductCode());
            if (!Objects.equals(first.getLedOrderId(), end.getLedOrderId())) {
                return error("请扫码同一分段订单的商品！");
            }

            barcodes = jcOrderBarcodeService.selectJcOrderBarcode(first.getLedOrderId(), first.getOrderBy(), end.getOrderBy());
            if (barcodes == null || barcodes.size() == 0) {
                return error("条码与商品对应不匹配");
            }

            for (JcOrderBarcode barcode : barcodes) {
                barcode.setUnloadTime(new Date());
            }
        } else {
            // 如果条码为空,则更新
            if (first.getUnloadTime() != null) {
                return error("商品已经卸车,请勿重复操作");
            }
            first.setUnloadTime(new Date());
            barcodes.add(first);
        }

        // 进行到站操作, 先修改为到站
        List<JcVehicleArrive> arrives = vehicleArriveService.selectJcVehicleArriveByShipmentId(shipment.getId(), shipment.getJcNowOrganizationId());
        if (shipment.getStatus() == OrderStatus.DESPATCH.getValue() || arrives.size() == 0) {
            vehicleArriveService.saveVehicleArrive(new Long[]{orderBarcodeVo.getShipmentId()});
        }

        return toAjax(jcOrderBarcodeService.updateBatchById(barcodes));
    }


    /**
     * 查询连续条码与商品对应列表
     *
     * @return 条码与商品对应集合
     */
    @ApiOperation("查询卸车商品")
    @PreAuthorize("@ss.hasPermi('api:barcode:unload:list')")
    @GetMapping("/getUnloadProductList")
    public TableDataInfo selectUnloadProductList(JcOrderBarcodeQueryVo pageVo) {
        JcOrderBarcode jcOrderBarcode = new JcOrderBarcode();
        jcOrderBarcode.setShipmentId(pageVo.getShipmentId());
        jcOrderBarcode.setLedOrderId(pageVo.getLedId());
        startPage();
        List<JcOrderBarcode> list = jcOrderBarcodeService.selectJcOrderUnloadList(jcOrderBarcode);
        return getDataTable(list);
    }


    /**
     * 修改保存条码与商品对应，只是用于修改商品装车状态，只有保存的时候才需要真正装载
     */
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("商品扫码送货")
    @Log(title = "条码与商品对应", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('api:barcode:send')")
    @PostMapping("/scanCodePreSend")
    public AjaxResult scanCodePreSend(@RequestBody JcLedSendBarcodeScanVo scanVo) {
        if (StringUtils.isBlank(scanVo.getProductCode())) {
            return error("条码不能为空");
        }
        JcOrderBarcode first = jcOrderBarcodeService.selectJcOrderBarcodeByProductCode(scanVo.getProductCode().replace("－", "-"));
        // 如果条码为空,则更新
        if (first == null) {
            return error("条码与商品对应不匹配");
        }
        if (first.getUnloadTime() == null) {
            return error("该运单还未运达，禁止派送！");
        }

        JcLed led = jcLedService.getById(first.getLedOrderId());
        if (led.getStatus() == OrderStatus.READY_SEND.getValue()) {
            return error("该商品对应的分段订单已经在派送中，请进行签收！");
        } else if (led.getStatus() != OrderStatus.TRANSPORT_FINISHED.getValue()) {
            return error("该商品对应的分段订单还未运输完毕，请确认订单！");
        }

            // 创建派送单
        JcLedSend send;
        if (scanVo.getSendId() != null) {
            send = jcLedSendService.selectJcLedSendBySendId(scanVo.getSendId());
            if (!send.getLedIds().contains(first.getLedOrderId().toString())) {
                send.setLedIds(send.getLedIds() + "," + first.getLedOrderId());
            }
        } else {
            // 查询send
            if (first.getSendId() != null) {
                send = jcLedSendService.selectJcLedSendBySendId(first.getSendId());
                if (send != null && !send.getLedIds().contains(first.getLedOrderId().toString())) {
                    send.setLedIds(send.getLedIds() + "," + first.getLedOrderId());
                }
            } else {
                // 查询未完成的派送单
                send = jcLedSendService.selectNoSendJcLedSendByUserId(SecurityUtils.getUserId());
                if (send == null) {
                    send = new JcLedSend();
                    send.setSendStatus("N");
                    send.setSendCode(redisCodeUtil.getSendCode());
                    send.setLedIds(first.getLedOrderId().toString());
                    send.setPreSendTime(new Date());
                    send.setPreSendUser(getUserId());
                    send.setPreSendUserDtLabel(getLoginUser().getUser().getNickName());
                }

            }
        }
        if (send != null && send.getSendId() != null) {
            jcLedSendService.updateById(send);
        } else {
            jcLedSendService.save(send);
        }

        List<JcOrderBarcode> barcodes = new ArrayList<>();
        if (StringUtils.isNotBlank(scanVo.getEndProductCode()) && !Objects.equals(scanVo.getProductCode(), scanVo.getEndProductCode())) {
            scanVo.setEndProductCode(scanVo.getEndProductCode().trim().replace("－", "-"));
            JcOrderBarcode end = jcOrderBarcodeService.selectJcOrderBarcodeByProductCode(scanVo.getEndProductCode());
            if (!Objects.equals(first.getLedOrderId(), end.getLedOrderId())) {
                return error("请扫码同一分段订单的商品！");
            }

            barcodes = jcOrderBarcodeService.selectJcOrderBarcode(first.getLedOrderId(), first.getOrderBy(), end.getOrderBy());
            if (barcodes == null || barcodes.size() == 0) {
                return error("条码与商品对应不匹配");
            }

            for (JcOrderBarcode barcode1 : barcodes) {
                barcode1.setSendId(send.getSendId());
                barcode1.setPreSendTime(new Date());
                barcode1.setPreSendUser(getUserId());
            }
        } else {
            first.setSendId(send.getSendId());
            first.setPreSendTime(new Date());
            first.setPreSendUser(getUserId());
            barcodes.add(first);
        }

        return toAjax(jcOrderBarcodeService.updateBatchById(barcodes)).put("send", send);
    }


    /**
     * 移除装载状态
     */
    @ApiOperation("移除商品预送货")
    @Log(title = "条码与商品对应", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('api:barcode:send:remove')")
    @PostMapping("/removeCodeSend/{productCode}")
    public AjaxResult removeCodeSend(@PathVariable("productCode") String productCode) {
        return toAjax(jcOrderBarcodeService.removeJcOrderBarcodeSend(productCode));
    }



    /**
     * 查询预派送商品
     *
     * @return 条码与商品对应集合
     */
    @ApiOperation("查询预派送商品")
    @PreAuthorize("@ss.hasPermi('api:barcode:send:list')")
    @GetMapping("/getPreSendProductList/{ledId}")
    public TableDataInfo getPreSendProductList(JcOrderBarcodeSendVo pageVo) {
        JcOrderBarcode jcOrderBarcode = new JcOrderBarcode();
        jcOrderBarcode.setSendId(pageVo.getSendId());
        jcOrderBarcode.setLedOrderId(pageVo.getLedId());
        startPage();
        List<JcOrderBarcode> list = jcOrderBarcodeService.selectJcOrderBarcodeList(jcOrderBarcode);
        return getDataTable(list);
    }



    /**
     * 确认所属货品卸车
     *
     * @param
     * @return
     */
    @PreAuthorize("@ss.hasPermi('api:barcode:send:finished')")
    @ApiOperation("确认扫码预送货")
    @PostMapping("/confirmSend/{sendId}")
    public AjaxResult confirmSend(@PathVariable Long sendId) {
        return toAjax(jcLedService.confirmSend(sendId));
    }

}
